package com.atguigu.spzx.manager.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.common.handler.exception.SpzxException;
import com.atguigu.spzx.common.util.consts.SpzxConst;
import com.atguigu.spzx.manager.interceptor.SpzxLoginAuthInterceptor;
import com.atguigu.spzx.manager.mapper.SysUserMapper;
import com.atguigu.spzx.manager.service.FileService;
import com.atguigu.spzx.manager.service.SysUserService;
import com.atguigu.spzx.model.dto.sys.LoginDto;
import com.atguigu.spzx.model.dto.sys.SysUserSearchDto;
import com.atguigu.spzx.model.entity.sys.SysUser;
import com.atguigu.spzx.model.result.ResultCodeEnum;
import com.atguigu.spzx.model.vo.sys.LoginVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class SysUserServiceImpl implements SysUserService {
    @Resource
    SysUserMapper sysUserMapper;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    FileService fileService;
    @Override
    public LoginVo login(LoginDto loginDto) {
        //1、判断参数格式
        String userName = loginDto.getUserName();
        String password = loginDto.getPassword();
        String code = loginDto.getCode();
        String codeKey = loginDto.getCodeKey();

        if(StringUtils.isEmpty(userName)
                || StringUtils.isEmpty(password)
                || StringUtils.isEmpty(code)
                || StringUtils.isEmpty(codeKey)){
//            throw new RuntimeException("账号或密码格式错误");
            throw new SpzxException(ResultCodeEnum.LOGIN_PARAMS_ERROR);
        }
        //=============校验验证码
        String cachedCode = stringRedisTemplate.opsForValue().get("sys:user:code:" + codeKey);
        if(StringUtils.isEmpty(cachedCode) || !code.equals(cachedCode)){
            throw new SpzxException(ResultCodeEnum.LOGIN_CODE_ERROR);
        }
        //2、根据账号查询用户信息
        SysUser sysUser = sysUserMapper.findSysUserByUsername(userName);
        if(sysUser==null){
//            throw new RuntimeException("账号不存在");
            throw new SpzxException(ResultCodeEnum.LOGIN_USERNAME_ERROR);
        }
        //3、账号正确：校验密码是否正确
        String encodedPwd = sysUser.getPassword();
        //前端传入的加密和数据库的密文比较： md5 相同的明文加密的结果一定相同(不可逆加密)  加盐加密
        String inputPwd = DigestUtils.md5DigestAsHex(password.getBytes());
        if(!inputPwd.equals(encodedPwd)){
//            throw new RuntimeException("密码错误");
            throw new SpzxException(ResultCodeEnum.LOGIN_PASSWORD_ERROR);
        }
        //删除code验证码
        stringRedisTemplate.delete(SpzxConst.LOGIN_USER_CODE_PREFIX + codeKey);
        //4、缓存登录状态：redis缓存
        //将用户信息转为json字符串再存入到redis中
        sysUser.setPassword(null);//脱敏： 清空敏感数据
        String json = JSON.toJSONString(sysUser);
        //存到redis中的key需要唯一
        //IdUtil提供的雪花算法id 长度为19位  由10进制数字组成  按照时间递增 的唯一id
        String token = IdUtil.getSnowflake(1, 1).nextIdStr();
        //不要使用大key
        stringRedisTemplate.opsForValue().set(SpzxConst.LOGIN_USER_KEY_PREFIX+token,json ,7 , TimeUnit.DAYS);
        //5、返回登录状态的token
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token); //只返回了token  redis查询数据时还需要和前缀字符串拼接才可以
        loginVo.setRefresh_token("111111");
        return loginVo;
    }

    @Override
    public SysUser getUserInfo() {
        //查询redis中的登录状态数据
//        String json = stringRedisTemplate.opsForValue().get(SpzxConst.LOGIN_USER_KEY_PREFIX + token);
//        if(StringUtils.isEmpty(json)){
//            throw new SpzxException(ResultCodeEnum.LOGIN_STATUS_ERROR);
//        }
//        SpzxLoginAuthInterceptor.SYS_USERS_MAP.get(token);
//        return JSON.parseObject(json,SysUser.class);
//        System.out.println(Thread.currentThread());
//        return SpzxLoginAuthInterceptor.SYS_USERS_MAP.get(Thread.currentThread());
        return SpzxLoginAuthInterceptor.THREAD_LOCAL.get();
    }

    @Override
    public void logout(String token) {
        stringRedisTemplate.delete(SpzxConst.LOGIN_USER_KEY_PREFIX+token);
    }

    @Override
    public PageInfo<SysUser> listUsers(SysUserSearchDto sysUserSearchDto, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<SysUser> sysUserList = sysUserMapper.selectByCodition(sysUserSearchDto);
        return new PageInfo<>(sysUserList);
    }

    @Override
    public void deleteById(Long id) {
        //查询用户头像
        SysUser sysUser = sysUserMapper.selectById(id);
        sysUserMapper.deleteById(id);
        //删除用户后删除头像文件
        if(!StringUtils.isEmpty(sysUser.getAvatar())){
            fileService.delete(sysUser.getAvatar());
        }

    }

    @Override
    public void save(SysUser sysUser) {
        /*
            用户名唯一性校验：
                =================
                    sysUser.getUsername() 查询数据库中是否存在对应的数据
         */

        //创建新用户时，密码需要加密
        sysUser.setPassword(DigestUtils.md5DigestAsHex(sysUser.getPassword().getBytes()));
        sysUserMapper.save(sysUser);
    }

    @Override
    public SysUser getById(Long id) {
        SysUser sysUser = sysUserMapper.selectById(id);
        sysUser.setPassword(null);
        return sysUser;
    }

    @Override
    public void update(SysUser sysUser) {
        sysUserMapper.update(sysUser);
    }

}
